﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;

namespace TibiaAutoHealer
{
    class Funcoes
    {
        #region Processo do tibia
        public static Process Tibia = Process.GetProcessesByName("Tibia")[0];
        public static uint baseAdress = Convert.ToUInt32(Tibia.MainModule.BaseAddress.ToInt32());
        public static IntPtr processHandle = WinAPI.OpenProcess(WinAPI.PROCESS_ALL_ACCESS, 0, (uint)Tibia.Id);
        #endregion

        #region DLL's
        //[DllImport("user32.dll")]
        //public static extern IntPtr WinAPI.SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        //[DllImport("kernel32.dll")]
        //public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

        //[DllImport("user32.dll", SetLastError = true)]
        //public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        #endregion

        #region Constantes de teclas
        public static uint WM_KEYDOWN = 0x100;
        public static uint WM_KEYUP = 0x101;//0x202;
        public static int VK_CONTROL = 0x11;
        public static int VK_SHIFT = 0x10;
        #endregion

        #region Endereços do Tibia
        public static uint Mana;
        public static uint XOR;
        public static uint HP;

        public static uint FullLightNop;
        public static uint FullLightAdr;
        public static byte[] FullLightNopDefault;
        public static byte[] FullLightNopEdited;
        public static byte FullLightAdrDefault;
        public static byte FullLightAdrEdited;

        public static uint Player_Experience;
        public static uint Player_Experience_Left;
        public static uint Player_Cap;
        public static uint Player_Level;
        public static uint Player_Name; //bug, precisa verificar!
        public static uint Player_Soul;
        public static uint Player_Z;
        public static uint Player_Y;
        public static uint Player_X;

        public static int BattleList_Start = 0x943008;
        public static int BattleList_Step = 0xB0;
        public static int BattleList_MaxCreatures = 0x514;
        public static uint BattleList_DistanceId = 0;
        public static uint BattleList_DistanceType = 3;
        public static uint BattleList_DistanceName = 4;
        public static uint BattleList_DistanceX = 44;
        public static uint BattleList_DistanceY = 40;
        public static uint BattleList_DistanceZ = 36;
        public static uint BattleList_DistanceIsWalking = 80;
        public static uint BattleList_DistanceDirection = 84;
        public static uint BattleList_DistanceLight = 124;
        public static uint BattleList_DistanceLightColor = 128;
        public static uint BattleList_DistanceHPBar = 140;
        public static int BattleList_End = BattleList_Start + (BattleList_Step * BattleList_MaxCreatures);
        #endregion

        #region Versao do Tibia
        public static string VersaoTibia()
        {
            return Funcoes.Tibia.MainModule.FileVersionInfo.FileVersion.ToString();
        }
        #endregion

        #region Função para usar Hotkey
        public static void Hotkey(string htk)
        {
            switch (htk)
            {
                case "F1":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F1, 0);
                    break;
                case "F2":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F2, 0);
                    break;
                case "F3":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F3, 0);
                    break;
                case "F4":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F4, 0);
                    break;
                case "F5":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F5, 0);
                    break;
                case "F6":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F6, 0);
                    break;
                case "F7":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F7, 0);
                    break;
                case "F8":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F8, 0);
                    break;
                case "F9":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F9, 0);
                    break;
                case "F10":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F10, 0);
                    break;
                case "F11":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F11, 0);
                    break;
                case "F12":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F12, 0);
                    break;
                case "Shift+F1":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F1, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F2":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F2, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F3":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F3, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F4":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F4, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F5":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F5, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F6":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F6, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F7":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F7, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F8":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F8, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F9":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F9, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F10":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F10, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F11":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F11, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Shift+F12":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_SHIFT, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F12, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_SHIFT, 1);
                    break;
                case "Control+F1":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F1, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F2":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F2, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F3":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F3, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F4":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F4, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F5":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F5, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F6":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F6, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F7":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F7, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F8":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F8, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F9":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F9, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F10":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F10, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F11":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F11, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
                case "Control+F12":
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.F12, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
            }
        }
        #endregion

        #region Função para retornar a quantidade da mana
        public static uint GetMana()
        {
            return Convert.ToUInt32(Memory.ReadInt32(Tibia.Handle, Mana) ^ Memory.ReadInt32(Tibia.Handle, XOR));
        }
        #endregion

        #region Função para retornar a quantidade do hp
        public static uint GetHP()
        {
            return Convert.ToUInt32(Memory.ReadInt32(Tibia.Handle, HP) ^ Memory.ReadInt32(Tibia.Handle, XOR));
        }
        #endregion

        #region Função para retornar XP do char
        public static uint GetXP()
        {
            return Convert.ToUInt32(Memory.ReadInt32(Tibia.Handle, Player_Experience));
        }
        #endregion

        #region Função para retornar CAP do char
        public static uint GetCAP()
        {
            return Convert.ToUInt32(Memory.ReadInt32(Tibia.Handle, Player_Cap) ^ Memory.ReadInt32(Tibia.Handle, XOR));
        }
        #endregion

        #region array magias
        public static string[] sMagias = { "exana flam", "exana kor", "exana mort", "exana pox", "exana vis", "exeta res", "exevo con", "exevo con flam", "exevo con grav", "exevo con hur", "exevo con mort", "exevo con pox", "exevo con vis", "exevo flam fur", "exevo frigo hur", "exevo gran frigo hur", "exevo gran mas flam", "exevo gran mas frigo", "exevo gran mas tera", "exevo gran mas vis", "exevo gran vis lux", "exevo mas san", "exevo pan", "exevo vis hur", "exevo vis lux", "exiva", "exori", "exori amp vis", "exori con", "exori flam", "exori frigo", "exori gran", "exori gran con", "exori gran flam", "exori gran frigo", "exori gran ico", "exori gran tera", "exori gran vis", "exori hur", "exori ico", "exori mas", "exori max flam", "exori max frigo", "exori max tera", "exori max vis", "exori min", "exori moe ico", "exori mort", "exori san", "exori tera", "exori vis", "exura", "exura gran", "exura gran ico", "exura gran mas res", "exura gran san", "exura ico", "exura san", "exura vita", "utamo mas sio", "utamo tempo", "utamo tempo san", "utamo vita", "utana vid", "utani gran hur", "utani hur", "utani tempo hur", "utevo gran lux", "utevo lux", "utevo vis lux", "utito mas sio", "utito tempo", "utito tempo san", "utori flam", "utori kor", "utori mas sio", "utori mort", "utori pox", "utori san", "utori vis", "utura", "utura gran", "utura mas sio" };
        #endregion

        #region say
        public static void Say(string text, int tempo)
        {
            foreach (char ch in text)
            {
                WinAPI.SendMessage(Tibia.MainWindowHandle, 0x102, Convert.ToChar(ch), 0);
                System.Threading.Thread.Sleep(tempo);
            }
            WinAPI.SendMessage(Tibia.MainWindowHandle, 0x102, 13, 0);
        }
        #endregion

        #region anti-afk
        public static void Dance()
        {
            Random rnd = new Random();
            int res = rnd.Next(1, 4);

            switch (res)
            {
                case 1:
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.Up, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, (int)Keys.Up, 1);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;

                case 2:
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.Down, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, (int)Keys.Down, 1);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;

                case 3:
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.Left, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, (int)Keys.Left, 1);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;

                case 4:
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, VK_CONTROL, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYDOWN, (int)Keys.Right, 0);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, (int)Keys.Right, 1);
                    WinAPI.SendMessage(Tibia.MainWindowHandle, WM_KEYUP, VK_CONTROL, 1);
                    break;
            }
        }
        #endregion

        #region Transformar em 32bits
        public static int ReadInt32(Process Tibia, uint Address)
        {
            IntPtr ptrBytesRead;
            byte[] buffer = new byte[4];
            WinAPI.ReadProcessMemory(Tibia.Handle, new IntPtr(Address), buffer, 4, out ptrBytesRead);
            return BitConverter.ToInt32(buffer, 0);
        }
        #endregion

        #region fullLight
        public static void FullLight(bool value)
        {
            if (value == true)
            {
                Memory.WriteBytes(processHandle, FullLightNop, FullLightNopEdited, 2);
                Memory.WriteByte(processHandle, FullLightAdr, FullLightAdrEdited);
            }
            else
            {
                Memory.WriteBytes(processHandle, FullLightNop, FullLightNopDefault, 2);
                Memory.WriteByte(processHandle, FullLightAdr, FullLightAdrDefault);
            }
        }
        #endregion

        #region ASLR
        public static void desabilitarASLR()
        {
            string regConteudo;
            regConteudo = @"Windows Registry Editor Version 5.00" + Environment.NewLine + Environment.NewLine;
            regConteudo += @"[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]" + Environment.NewLine;
            regConteudo += "\"MoveImages\"=dword:00000000";

            if (!File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\ASLR.reg"))
            {
                StreamWriter sw = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\ASLR.reg");
                sw.Write(regConteudo);
                sw.Close();

                Process regedit = Process.Start(System.IO.Directory.GetCurrentDirectory() + "\\ASLR.reg");
                regedit.WaitForExit();
            }

        }
        #endregion

        #region calc_exp
        public static uint CalulaExp()
        {
            var xpAtual = GetXP() * 1 ;
            var levelDesejado = (LevelChar() + 1) * 1 - 1;
            var formula = (((50 * levelDesejado) * (levelDesejado) * (levelDesejado) - 150 * (levelDesejado) * (levelDesejado) + 400 * (levelDesejado)) / 3);

            return formula - xpAtual;
        }
        #endregion

        #region level do char
        public static uint LevelChar()
        {
            return Convert.ToUInt32(Memory.ReadInt32(Tibia.Handle, Player_Level));
        }
        #endregion

        #region player soul
        public static int PlayerSoul()
        {
            return Memory.ReadInt32(Tibia.Handle, Player_Soul);
        }
        #endregion

        #region funcao para ler algum byte
        public static uint LerByte(uint _byte, bool baseAdr)
        {
            uint ret;
            if (baseAdr)
            {
                ret = Convert.ToUInt32(ReadInt32(Tibia, _byte + baseAdress));
            }
            else
            {
                ret = Convert.ToUInt32(ReadInt32(Tibia, _byte));
            }
            return ret;            
        }
        #endregion

        #region Player no battle list
        //Está bugado, não está pegando o nome do char logado =\
        public static List<string> GetPlayers(int tipo)
        {
            List<string> strItens = new List<string>();
            for (int i = (int)BattleList_Start; i <= (int)BattleList_End; i += (int)BattleList_Step)
            {
                uint isVisible = Memory.ReadUInt32(Tibia.Handle, i + 172);
                int Type = Memory.ReadByte(Tibia.Handle, i + 3);
                string name = Memory.ReadString(Tibia.Handle, i + 4);

                // -1 = tudo
                if (tipo == -1)
                {
                    if (isVisible == 1)
                    {
                        strItens.Add(name);
                    }
                }
                else
                {
                    if (isVisible == 1 && Type == tipo)
                    {
                        strItens.Add(name);
                    }
                }
                
            }
            return strItens;
        }
        #endregion
    }
}
